package com.gitee.ice1938;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.http.MediaType;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

@SpringBootApplication
public class Application {
	private static final Logger log = LoggerFactory.getLogger(Application.class);

	public static void main(String[] args) {
		SpringApplication app = new SpringApplication(Application.class);
		ConfigurableApplicationContext appContext = app.run(args);
		logApplicationStartup(appContext);
	}

	private static void logApplicationStartup(ConfigurableApplicationContext appContext) {
		Environment env = appContext.getEnvironment();
		String protocol = "http";
		if (env.getProperty("server.ssl.key-store") != null) {
			protocol = "https";
		}
		String serverPort = env.getProperty("server.port");
//		if (serverPort == null) {
//			AbstractConfigurableEmbeddedServletContainer swf = appContext.getBean(AbstractConfigurableEmbeddedServletContainer.class);
//			serverPort = String.valueOf(swf.getPort());
//		}
		String contextPath = env.getProperty("server.servlet.context-path");
		if (!StringUtils.hasText(contextPath)) {
			contextPath = "/";
		}
		String hostAddress = "localhost";
		try {
			hostAddress = InetAddress.getLocalHost().getHostAddress();
		} catch (UnknownHostException e) {
			log.warn("The host name could not be determined, using `localhost` as fallback");
		}
		log.info("\n----------------------------------------------------------\n\t" //
				+ "Application '{}' is running! Access URLs:\n\t" //
				+ "Local: \t\t{}://localhost:{}{}\n\t"//
				+ "External: \t{}://{}:{}{}\n\t" //
				+ "h2-console: \t{}://{}:{}{}" //
				+ "\n\tProfile(s): \t{}"//
				+ "\n----------------------------------------------------------",
				env.getProperty("spring.application.name"), //
				protocol, serverPort, contextPath, //
				protocol, hostAddress,serverPort, contextPath, //
				protocol, hostAddress,serverPort, contextPath+"h2-console", //
				env.getActiveProfiles());
	}

	/**
	 * {@link View} backed by an HTML resource.
	 */
	private static class HtmlResourceView implements View {

		private StringBuffer body;

		HtmlResourceView(HttpServletRequest request, Map<String, Object> model) {
			ApplicationContext applicationContext = WebApplicationContextUtils
					.getWebApplicationContext(request.getServletContext());
			RequestMappingHandlerMapping requestMappingHandlerMapping = applicationContext
					.getBean(RequestMappingHandlerMapping.class);
			Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
			this.body = new StringBuffer();
			body.append("<!DOCTYPE html>");
			body.append("<html><head><meta charset=\"utf-8\">");

			body.append("<title>Simple Index</title>");
			body.append("</head>");
			body.append("<body>");
			body.append("<hr>");
			for (Entry<String, Object> element : model.entrySet()) {
				body.append(element.toString());
				body.append("<br>");
			}
			body.append("<hr>");
			for (Entry<RequestMappingInfo, HandlerMethod> item : handlerMethods.entrySet()) {
				HandlerMethod value = item.getValue();
				if (value.getBean().equals("basicErrorController")) {
					continue;
				}
				RequestMappingInfo key = item.getKey();
				RequestMethodsRequestCondition method = key.getMethodsCondition();
				PatternsRequestCondition prc = key.getPatternsCondition();
				Set<String> patterns = prc.getPatterns();
				if (patterns.size() > 1) {
					// logger.warn(" MethodAnnotation have more patterns :{}",
					// prc.toString());
					// continue;
				}
				ResponseBody responseBody = value.getMethodAnnotation(ResponseBody.class);
				for (String reqUri : patterns) {
					if (reqUri.endsWith("/")) {
						reqUri = reqUri.substring(0, reqUri.length() - 1);
					}
					// 不是页面跳转方法
					if (responseBody == null) {
						if (!method.isEmpty() && !method.getMethods().contains(RequestMethod.GET)) {
							// logger.info("reqUri must be GET, {} method:{}",
							// reqUri, method);
							continue;
						}
						// 约定菜单不能包含path变量
						if (reqUri.contains("{")) {
							// logger.info("reqUri can't has pathvalue :{},method:{}",
							// reqUri, method);
							continue;
						}
						// 跳转页面的方法<a href="http://www.123.com">访问!</a>
						body.append("<a target =\"_blank\" href=\"");
						body.append(request.getContextPath());
						body.append(reqUri);
						body.append("\">");
						body.append(value.getBean());
						body.append(":");
						body.append(reqUri);
						body.append("</a><hr>");

					}
				}
			}
			body.append("</body></html>");
		}

		@Override
		public String getContentType() {
			return MediaType.TEXT_HTML_VALUE;
		}

		@Override
		public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
				throws Exception {
			response.setContentType(getContentType());
			InputStream input = new ByteArrayInputStream(body.toString().getBytes());
			FileCopyUtils.copy(input, response.getOutputStream());
		}

	}
}